package com.lkf.simplewebcontainer.http.impl;

import com.lkf.simplewebcontainer.http.Response;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.DefaultFileRegion;
import io.netty.handler.codec.http.*;

import javax.activation.MimetypesFileTypeMap;
import java.io.File;

/**
 * 对rresponse规范的简单实现
 * 利用netty提供的HttpRequest实现request
 * 利用netty提供的ChannelHandlerContext实现context上下文操作
 */
public class SimpleResponse implements Response {

    private HttpRequest request;
    private ChannelHandlerContext context;

    public SimpleResponse(HttpRequest request, ChannelHandlerContext context) {
        this.request = request;
        this.context = context;
    }


    /**
     * 构造 http response 响应
     *
     * @param content 文本响应内容
     * @throws Exception
     */
    @Override
    public void write(String content, HttpResponseStatus status, String contentType) throws Exception {
        // 创建响应对象
        FullHttpResponse response = new DefaultFullHttpResponse(
                // http版本
                HttpVersion.HTTP_1_1,
                // 响应码
                status,
                // 响应内容
                // 根据响应体内容大小为response对象分配存储空间
                // content.getBytes方法可能抛出java.io.UnsupportedEncodingException
                Unpooled.wrappedBuffer(content.getBytes("UTF-8")));
        // 获取响应头
        HttpHeaders headers = response.headers();
        // 设置响应文本类型
        // 默认使用text/json
        // 对于非文本内容如静态资源、文件需使用其他type
        headers.set(HttpHeaderNames.CONTENT_TYPE, contentType);
        // 根据响应文本设置响应长度
        headers.set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        // 设置缓存过期时间
        // 0不缓存，每次客户端（浏览器）产生请求都会访服务端，不访问客户端本地缓存
        headers.set(HttpHeaderNames.EXPIRES, 0);
        // 设置是否为长连接
        // 若HTTP请求是长连接，则响应也使用长连接
        if (HttpUtil.isKeepAlive(request)) {
            headers.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
        }
        // 将构造好的响应写入到netty的channel中
        context.writeAndFlush(response);
    }

    @Override
    public void writeFile(File file, HttpResponseStatus status, String contentType) throws Exception {

        HttpHeaders headers = getContentTypeHeader(file);
        // 创建响应对象
        HttpResponse response = new DefaultHttpResponse(
                // http版本
                HttpVersion.HTTP_1_1,
                // 响应码
                status, headers);
        // 将构造好的响应写入到netty的channel中
        context.write(response);
        context.write(new DefaultFileRegion(file, 0, file.length()));
        context.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
//        context.close();
    }

    private HttpHeaders getContentTypeHeader(File file) {
        MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
        HttpHeaders headers = new DefaultHttpHeaders();
        String contentType = mimeTypesMap.getContentType(file);
        if (contentType.equals("text/plain")) {
            //由于文本在浏览器中会显示乱码，此处指定为utf-8编码
            contentType = "text/plain;charset=utf-8";
        }
        headers.set(HttpHeaderNames.CONTENT_TYPE, contentType);
        return headers;
    }
}
